﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Wardriver
{
    public class GPSEntry 
    {
        private double _Longitude;
        private double _Latitude;
        private DateTime _SystemTime;
        private DateTime _GPSTime;

        /// <summary>
        /// The Latitude value
        /// </summary>
        public double Latitude { get { return _Latitude; } }

        /// <summary>
        /// The Longitude value
        /// </summary>
        public double Longitude { get { return _Longitude; } }

        /// <summary>
        /// The system time at time of Fix.
        /// </summary>
        public DateTime SystemTime { get { return _SystemTime; } }

        /// <summary>
        /// The GPS time at time of Fix.
        /// </summary>
        public DateTime GPSTime { get { return _GPSTime; } }

        /// <summary>
        /// Used formula for spherical distance to find the distance between to GPS points. 
        /// </summary>
        /// <param name="other">The other GPS coordinate</param>
        /// <returns>Distance in Km.</returns>
        public double Distance(GPSEntry other) 
        {
            // http://grapevine.abe.msstate.edu/~fto/calculator/converte.html

            double t1 = Math.Sin(Rad(this.Latitude)) * Math.Sin(Rad(other.Latitude));
            double t2 = Math.Cos(Rad(this.Latitude)) * Math.Cos(Rad(other.Latitude));
            double t3 = Math.Cos(Rad(other.Longitude - this.Longitude));
            double t4 = t2 * t3;
            double t5 = t1 + t4;
            double rad_dist = Math.Atan(-(t5 / Math.Sqrt(-t5 * t5 + 1))) + 2 * Math.Atan(1);

            double dist_miles = rad_dist * 3437.74677 * 1.1508;
            double dist_km = dist_miles * 1.6093470878864446;

            return dist_km;
        }

        /// <summary>
        /// Convert degrees to radians.
        /// </summary>
        internal static double Rad(double deg)
        {
            return deg * Math.PI / 180;
        }

        /// <summary>
        /// Convert radians to degrees.
        /// </summary>
        internal static double Deg(double rad)
        {
            return rad * 180 / Math.PI;
        }

        /// <summary>
        /// Basic GPS Entry. Has coordinates.
        /// </summary>
        /// <param name="Long">The Longitude value</param>
        /// <param name="Lat">The Latitude value</param>
        public GPSEntry(double Long, double Lat) 
        {
            this._Latitude = Lat;
            this._Longitude = Long;
            this._SystemTime = DateTime.MinValue;
            this._GPSTime = DateTime.MinValue;
        }

        /// <summary>
        /// Expanded GPS Entry. Has coordinates as well as time.
        /// </summary>
        /// <param name="Long">The Longitude value</param>
        /// <param name="Lat">The Latitude value</param>
        /// <param name="SystemTime">The system time at time of Fix.</param>
        /// <param name="GPSTime">The GPS time at time of Fix.</param>
        public GPSEntry(double Long, double Lat, DateTime SystemTime, DateTime GPSTime)
        {
            this._Latitude = Lat;
            this._Longitude = Long;
            this._SystemTime = SystemTime;
            this._GPSTime = GPSTime;
        }
    }
}
